package system

import (
	"errors"
	"github.com/gin-gonic/gin"
	uuid "github.com/satori/go.uuid"
	"gorm.io/datatypes"
	"gorm.io/gorm"
	"server/global"
	comRequest "server/model/common/request"
	sysModel "server/model/system"
	sysRequest "server/model/system/request"
	"server/utils"
)

var UserServiceApp = new(UserService)

type UserService struct {
}

//密码获取方法，不直接将密码以md5暴露，需要设置盐
func (u *UserService) Password(pwd string) string {
	secretPwd := "web_gin:" + pwd
	return utils.MD5V([]byte(secretPwd))
}

//用户登录处理方法
func (u *UserService) Login(l *sysRequest.Login) (user *sysModel.SysUser, err error) {
	err = global.GvaDb.Where("email = ? AND password = ?", l.Username, u.Password(l.Password)).First(&user).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户账号或密码错误")
		}
		return nil, err
	}
	return
}

//通过uuid获取用户信息
func (u *UserService) GetUserByUuid(uuid uuid.UUID) (user *sysModel.SysUser, err error) {
	reqUser := &sysModel.SysUser{}
	err = global.GvaDb.Preload("Roles").First(reqUser, "uuid = ?", uuid).Error
	return reqUser, err
}

//通过用户ID更新用户数据
func (u *UserService) UpdateUser(userId uint, data *sysRequest.SysUserUpdate) error {
	user, err := u.GetUserById(userId)
	if err != nil {
		return err
	}
	return global.GvaDb.Model(user).Where("id = ?", userId).Updates(sysModel.SysUser{
		Name:           data.Name,
		Avatar:         data.Avatar,
		Tags:           data.Tags,
		Country:        data.Country,
		CountryName:    data.CountryName,
		Geographic:     data.Geographic,
		GeographicName: data.GeographicName,
		Address:        data.Address,
		Phone:          data.Phone,
		Profile:        data.Profile,
	}).Error
}

//通过用户ID获取用户信息
func (u *UserService) GetUserById(id uint) (*sysModel.SysUser, error) {
	reqUser := &sysModel.SysUser{}
	err := global.GvaDb.Where("`id` = ?", id).First(reqUser).Error
	return reqUser, err
}

//修改密码
func (u *UserService) UpdatePwd(userId uint, data *sysRequest.ResetPwdRequest) error {
	user, err := u.GetUserById(userId)
	if err != nil {
		return err
	}
	if u.Password(data.OldPassword) != user.Password {
		return errors.New("旧密码不正确")
	}
	if data.NewPassword != data.ConfirmPassword {
		return errors.New("输入的两次密码不一致")
	}
	if u.Password(data.NewPassword) == user.Password {
		return errors.New("新密码与旧密码一致")
	}
	return global.GvaDb.Where(&sysModel.SysUser{ID: userId}).Updates(sysModel.SysUser{Password: u.Password(data.NewPassword), PasswordLevel: data.PasswordLevel}).Error
}

//通过邮箱查找用户数据
func (u *UserService) FindByEmail(ctx *gin.Context, email string) (*sysModel.SysUser, error) {
	var user *sysModel.SysUser
	result := global.GvaDb.Where(&sysModel.SysUser{Email: email}).Limit(1).Find(&user)
	return user, result.Error
}

//通过邮箱查找用户数据
func (u *UserService) FindById(ctx *gin.Context, id uint32) (*sysModel.SysUser, error) {
	var user *sysModel.SysUser
	result := global.GvaDb.First(&user, id)
	return user, result.Error
}

// 获取用户分页列表
func (u *UserService) GetPageList(p *sysRequest.SysUserGetList) ([]*sysModel.SysUser, int64, error) {
	var list []*sysModel.SysUser
	var total int64
	tx := global.GvaDb.Model(&sysModel.SysUser{})
	if p.Name != "" {
		tx = tx.Where("name like ?", "%"+p.Name+"%")
	}
	if p.Email != "" {
		tx = tx.Where("email like ?", "%"+p.Email+"%")
	}
	if p.Status == 1 { //激活

	} else if p.Status == 2 { //禁用
		tx = tx.Unscoped().Where("deleted_at IS NOT NULL")
	} else {
		tx = tx.Unscoped()
	}
	err := tx.Count(&total).Order("id DESC").Limit(int(p.PageSize)).Offset(int((p.PageNo - 1) * p.PageSize)).Find(&list).Error
	//转换用户角色json数据
	for _, res := range list {
		//清空密码数据
		res.Password = ""
	}
	return list, total, err
}

// 保存用户数据
func (u *UserService) SaveUser(data *sysModel.SysUser) error {
	var err error
	return global.GvaDb.Transaction(func(tx *gorm.DB) error {
		if data.Geographic == nil {
			data.Geographic = datatypes.JSON("{}")
		}
		//更新用户表
		if data.ID != 0 {
			if err := tx.Unscoped().Updates(data).Error; err != nil {
				return err
			}
		} else {
			if err := tx.Create(&data).Error; err != nil {
				return nil
			}
		}
		//先查所有角色
		var roles []sysModel.SysRole
		//解析角色ID
		var userRoleList []sysRequest.SysUserRoleIdVal
		json.Unmarshal(data.RoleIds, &userRoleList)
		//获取权限ID
		var roleIds []uint
		for _, val := range userRoleList {
			roleIds = append(roleIds, val.Value)
		}
		//查询角色列表
		tx.Model(&sysModel.SysRole{}).Find(&roles, roles)
		//替换用户角色关联关系
		err = tx.Model(data).Association("Roles").Replace(roles)
		if err != nil {
			return err
		}
		//更新casbin策略-先删除该用户关联角色
		_, err := CasbinServiceApp.Casbin().RemoveFilteredGroupingPolicy(0, string(data.ID))
		if err != nil {
			return err
		}
		//更新casbin策略-添加该用户拥有角色
		for _, role := range roles {
			if _, err := CasbinServiceApp.Casbin().AddGroupingPolicy(string(data.ID), role.Name); err != nil {
				return err
			}
		}
		return nil
	})
}

//禁用用户
func (u *UserService) DisableUser(ids *comRequest.IdsReq) error {
	return global.GvaDb.Transaction(func(tx *gorm.DB) error {
		//禁用即删除用户数据
		if err := tx.Delete(&sysModel.SysUser{}, ids.Ids).Error; err != nil {
			return err
		}
		//删除用户关联角色数据
		return nil
	})
}

//激活用户
func (u *UserService) EnableUser(ids *comRequest.IdsReq) error {
	return global.GvaDb.Transaction(func(tx *gorm.DB) error {
		//恢复用户
		if err := tx.Model(&sysModel.SysUser{}).Select("deleted_at").Unscoped().Where("id in ?", ids.Ids).Updates(map[string]interface{}{"deleted_at": nil}).Error; err != nil {
			return err
		}
		return nil
	})
}
